#include <assert.h>
#include <stddef.h>
#include <stdlib.h>
#include <stdbool.h>
#include <stdio.h>
typedef int STDataType;
typedef struct Stack
{
    STDataType* _data;
    int _top;       // 栈顶
    int _capacity;  // 容量 
}Stack;
void StackInit(Stack* ps)
{   
    assert(ps);
    ps->_data = (STDataType*)malloc(sizeof(STDataType)*4);
    if (ps->_data == NULL)
    {
        perror("mallloc fail:");
        exit(-1);
    }
    ps->_top = 0;
    ps->_capacity = 4;
    
}
// 入栈 
void StackPush(Stack* ps, STDataType data)
{
    assert(ps);
    if (ps->_top == ps->_capacity)
    {
        STDataType* tmp = (STDataType*)realloc(ps->_data,sizeof(STDataType) * ps->_capacity * 2);
        if (tmp == NULL)
        {
            perror("realloc fail:");
            exit(-1);
        }
        ps->_capacity *= 2;
        ps->_data= tmp;
    }
    ps->_data[ps->_top] = data;
    ps->_top++;

}
// 出栈 
void StackPop(Stack* ps)
{
    ps->_top--;
}
// 获取栈顶元素 
STDataType StackTop(Stack* ps)
{
    assert(ps);
    assert(ps->_top > 0);
    return ps->_data[ps->_top - 1];
}
// 获取栈中有效元素个数 
int StackSize(Stack* ps)
{
    return ps->_top;
}
// 检测栈是否为空，如果为空返回非零结果，如果不为空返回0 
int StackEmpty(Stack* ps)
{
    return ps->_top == 0;//如果top为0，返回true
}
// 销毁栈 
void StackDestroy(Stack* ps)
{
    free(ps->_data);
    ps->_top = 0;
    ps->_capacity = 0;
}


typedef struct {
    Stack push;//入列“缓冲区” 当没有出列元素在pop中，把push中的元素放到pop中准备出列
    Stack pop; //出列“准备区” 当pop出列完后 再问push要元素 pop的栈顶=队头
} MyQueue;
bool myQueueEmpty(MyQueue* obj);
int myQueuePeek(MyQueue* obj);

MyQueue* myQueueCreate() {
    MyQueue* newQueue=(MyQueue*)malloc(sizeof(MyQueue));
    StackInit(&newQueue->push);
    StackInit(&newQueue->pop);
    return newQueue;
}

void myQueuePush(MyQueue* obj, int x) { //入栈入到缓冲区 也就是入列
    assert(obj);
    StackPush(&obj->push,x);
}

int myQueuePop(MyQueue* obj) {//出列即是出列准备区pop（栈）中的栈顶出栈
    assert(obj);
    assert(!myQueueEmpty(obj));
    int peek=myQueuePeek(obj);
    StackPop(&obj->pop);
    return peek;
}

int myQueuePeek(MyQueue* obj) {
    assert(obj);
    assert(!myQueueEmpty(obj));
//当pop全部出列完为空时，重新把又入列push的元素放到pop中准备出列
    if(StackEmpty(&obj->pop))
    {
        while(!StackEmpty(&obj->push))
        {
            StackPush(&obj->pop,StackTop(&obj->push));
            StackPop(&obj->push);
        }
    }
    return StackTop(&obj->pop);//返回出列准备区的栈顶 即队头

}

bool myQueueEmpty(MyQueue* obj) {
    assert(obj);
    return StackEmpty(&obj->push) && StackEmpty(&obj->pop);
}

void myQueueFree(MyQueue* obj) {
    assert(obj);
    StackDestroy(&obj->push);
    StackDestroy(&obj->pop);
    free(obj);
}

